package com.warningrc.module.language.interceptor;

import java.util.Locale;
import java.util.Map;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
import com.opensymphony.xwork2.interceptor.I18nInterceptor;
import com.opensymphony.xwork2.util.LocalizedTextUtil;
import com.opensymphony.xwork2.util.ValueStack;
import com.warningrc.system.Constants;
import com.warningrc.system.lang.WarningLogger;

/**
 * set locale for struts2
 * 
 */
@SuppressWarnings("serial")
public class DefaultLanguageInterceptor extends AbstractInterceptor {
	private static final String IS_SET_LOACLE = "_DefaultLanguageInterceptor_is_set_locale_";

	private static WarningLogger log = WarningLogger
			.getWarningLogger(DefaultLanguageInterceptor.class);

	@SuppressWarnings("unchecked")
	@Override
	public String intercept(ActionInvocation invocation) throws Exception {
		ActionContext actionContext = invocation.getInvocationContext();
		ValueStack valueStack = invocation.getStack();
		// 查看当前请求是否已经设置过语言环境
		boolean isSetLocale = Boolean.parseBoolean(String.valueOf(valueStack
				.findValue(IS_SET_LOACLE)));
		if (!isSetLocale) {
			Locale locale = findLoacle(actionContext);
			// 设置ActionContext的语言环境
			log
					.info("\u5C06struts2\u7684\u8BED\u8A00\u73AF\u5883\u8BBE\u7F6E\u4E3A\uFF1A"
							+ locale);
			actionContext.setLocale(locale);
			// 在值栈中存放一个boolean值，来标记当前请求已经设置过语言环境
			valueStack.set(IS_SET_LOACLE, true);
		}
		return invocation.invoke();
	}

	/**
	 * 从Map集合中获取指定元素的值
	 * 
	 * @param params
	 * @param parameterName
	 * @return
	 */
	private static Object findLocaleParameter(Map<String, Object> params,
			String parameterName) {
		Object requested_locale = params.get(parameterName);
		if (requested_locale != null && requested_locale.getClass().isArray()
				&& ((Object[]) requested_locale).length == 1) {
			requested_locale = ((Object[]) requested_locale)[0];
		}
		return requested_locale;
	}

	/**
	 * 
	 * @param actionContext
	 * @return
	 */
	private static Locale findLoacle(ActionContext actionContext) {
		Locale locale = null;
		// 获取request的参数列表
		Map<String, Object> params = actionContext.getParameters();
		// 获取session
		Map<String, Object> session = actionContext.getSession();
		// 获取request中request_locale参数值
		Object requested_locale = findLocaleParameter(params,
				I18nInterceptor.DEFAULT_PARAMETER);
		log.debug("\u83B7\u53D6request Parameter\u4E2D\u7684"
				+ I18nInterceptor.DEFAULT_PARAMETER + "\u53C2\u6570\u503C");
		// 如果request中request_locale参数值为null，则获取request_only_locale参数值
		if (requested_locale == null) {
			log.debug("request Parameter\u4E2D\u4E0D\u5B58\u5728"
					+ I18nInterceptor.DEFAULT_PARAMETER + "\u53C2\u6570\u503C");
			log.debug("\u83B7\u53D6request Parameter\u4E2D\u7684"
					+ I18nInterceptor.DEFAULT_REQUESTONLY_PARAMETER
					+ "\u53C2\u6570\u503C");
			requested_locale = findLocaleParameter(params,
					I18nInterceptor.DEFAULT_REQUESTONLY_PARAMETER);
			// 如果request中request_only_locale参数值为null，则从session中获取WW_TRANS_I18N_LOCALE值，该值是struts2
			// 框架中的i18n拦截器根据request的request_locale参数值设置的语言环境
			if (requested_locale == null) {
				log.debug("request Parameter\u4E2D\u4E0D\u5B58\u5728"
						+ I18nInterceptor.DEFAULT_REQUESTONLY_PARAMETER
						+ "\u53C2\u6570\u503C");
				log.debug("\u83B7\u53D6session\u4E2D\u7684"
						+ I18nInterceptor.DEFAULT_SESSION_ATTRIBUTE
						+ "\u53C2\u6570\u503C");
				requested_locale = session
						.get(I18nInterceptor.DEFAULT_SESSION_ATTRIBUTE);
				// 如果session中不存在WW_TRANS_I18N_LOCALE值，则获取ActionContext的语言环境
				if (requested_locale == null) {
					log.debug("session\u4E2D\u4E0D\u5B58\u5728"
							+ I18nInterceptor.DEFAULT_SESSION_ATTRIBUTE
							+ "\u53C2\u6570\u503C");
					log
							.debug("\u83B7\u53D6ActionContext\u4E2D\u7684Locale\u503C");
					requested_locale = actionContext.getLocale();
				}
			}
		}
		// 如果requested_locale为null，则将locale设置为国际化资源文件(config.properties.language)中配置的(warning.language.default)默认语言环境;
		// 如果requested_locale类型为Locale，则直接赋值给locale;
		// 如果上述两项都不匹配，则根据requested_locale初始化一个Locale对象
		locale = (requested_locale instanceof Locale) ? (Locale) requested_locale
				: (requested_locale != null ? LocalizedTextUtil
						.localeFromString(requested_locale.toString(),
								Constants.getLanguages().getDefaultLocale())
						: Constants.getLanguages().getDefaultLocale());
		// 如果国际化资源文件中配置的语言环境不包含上述获取的语言环境，则将locale赋值为国际化资源文件中配置的默认语言环境
		if (!Constants.getLanguages().getLocales().containsValue(locale)) {
			log
					.info("\u56FD\u9645\u5316\u8D44\u6E90\u6587\u4EF6\u4E2D\u914D\u7F6E\u7684\u8BED\u8A00\u73AF\u5883\u4E0D\u5305\u542B "
							+ locale
							+ ",\u5C06locale\u8D4B\u503C\u4E3A\u914D\u7F6E\u7684\u9ED8\u8BA4\u8BED\u8A00");
			locale = Constants.getLanguages().getDefaultLocale();
		}
		return locale;
	}
}
